use rusqlite::{Connection, Result};
use rusqlite::types::FromSql;

pub fn init(conn :& Connection) -> Result<()> {
    // 创建码表控制
    conn.execute(
    "CREATE TABLE if not exists code(
              name text(30) PRIMARY KEY,
              region text(10) DEFAULT 'default',
              def_val text,
              val text
            )",
    (),
    )?;

    // 创建索引
    conn.execute(
    "CREATE INDEX if not exists idx_region ON code (
              region COLLATE BINARY DESC
            )",
    (),
    )?;

    init_code(conn, "meta", "version", "v1.0");
    init_code(conn, "defalut", "auto", "true");

    Ok(())
}


/**
 * 码表
*/
#[derive(Debug, Clone)]
pub struct Code {
    pub name: String,
    pub region: String,
    pub val: String,
}

impl Code {
    pub fn new(name: &str, region: &str, def_val: Option<&str>, val: Option<&str>) -> Code {
        Code {
            name: name.to_string(),
            region: region.to_string(),
            val: val.unwrap_or(def_val.unwrap_or("")).to_string(),
        }
    }
}

/**
 * 获取码表
*/
pub fn get_code(conn :& Connection, name: &str) -> Option<Code> {
    get_code_full(conn, "default", name)
}

/**
 * 获取码表
*/
pub fn get_code_full(conn :& Connection, region: &str, name: &str) -> Option<Code> {
    let mut stmt = match conn.prepare("SELECT region, name, def_val, val FROM code WHERE region = ? AND name = ?") {
      Ok(stmt) => stmt,
      Err(e) => {
          return None;
      }
    };

    let code_iter = match stmt.query_map([region, name], |row| {
        Ok(Code {
            name: row.get(1)?,
            region: row.get(0)?,
            val: row.get(3)?,
        })
    }) {
        Ok(code_iter) => code_iter,
        Err(e) => {
            return None;
        }
    };

    let mut code = None;
    for c in code_iter {
        match c {
            Ok(c) => code = Some(c),
            Err(e) => { }
        }
        break;
    }

    code
}

/**
 * 根据分区获取码表列表
*/
pub fn get_code_list(conn :& Connection, region: &str) -> Vec<Code> {
    let mut stmt = match conn.prepare("SELECT region, name, def_val, val FROM code WHERE region = ?") {
        Ok(stmt) => stmt,
        Err(e) => {
            return Vec::new();
        }
    };
    let iter = match stmt.query_map([region], |row| {
        Ok(Code {
            name: row.get(1)?,
            region: row.get(0)?,
            val: row.get(3)?,
        })
    }) {
        Ok(code_iter) => code_iter,
        Err(e) => {
            return Vec::new();
        }
    };

    iter.filter_map(|c|{
        c.ok()
    }).collect()
    // let mut code = Vec::new();
    // for c in code_iter {
    //     match c {
    //         Ok(c) => code.push(c),
    //         Err(e) => { }
    //     }
    // }
    //
    // code
}

/**
 * 保存码表
*/
pub fn save_code(conn :&Connection, code: &Code) -> Result<(bool)> {
    Ok(conn.execute(
        "INSERT OR REPLACE INTO code (name, region, val) VALUES (?1, ?2, ?3)",
        (
            &code.name,
            &code.region,
            &code.val,
        ),
    )? > 0)
}

/**
 * 初始化码表
*/
pub fn init_code(conn: &Connection, region: &str, name: &str, def_val: &str) -> Result<(bool)> {

    if (conn.execute(
        "UPDATE code set def_val = ?1 where region= ?2 and name = ?3",
        (
            def_val,
            region,
            name,
        ),
    )? > 0) {
        return Ok(true);
    }

    Ok(conn.execute(
        "INSERT OR REPLACE INTO code (name, region, def_val) VALUES (?1, ?2, ?3)",
        (
            name,
            region,
            def_val,
        ),
    )? > 0)
}